//package cn.sw.cloudmybatisplus.common.mapper;
//
//import java.lang.reflect.Field;
//
//public class Mapper {
//
//    public static <S, T> T map(S source, Class<T> targetClass) throws Exception {
//        T target = targetClass.getDeclaredConstructor().newInstance();
//        mapFields(source, target);
//        return target;
//    }
//
//    private static void mapFields(Object source, Object target) throws IllegalAccessException {
//        if (source == null || target == null) {
//            return;
//        }
//
//        Class<?> sourceClass = source.getClass();
//        Class<?> targetClass = target.getClass();
//
//        // Map fields from source to target, including fields in superclasses
//        mapFieldsRecursive(source, target, sourceClass, targetClass);
//    }
//
//    private static void mapFieldsRecursive(Object source, Object target, Class<?> sourceClass, Class<?> targetClass) throws IllegalAccessException {
//        if (sourceClass == null || targetClass == null || sourceClass.equals(Object.class)) {
//            return;
//        }
//
//        // Map fields from source to target
//        for (Field sourceField : sourceClass.getDeclaredFields()) {
//            sourceField.setAccessible(true);
//            Field targetField = getFieldByName(targetClass, sourceField.getName());
//            if (targetField != null) {
//                targetField.setAccessible(true);
//                if (sourceField.getType().equals(targetField.getType())) {
//                    targetField.set(target, sourceField.get(source));
//                }
//            }
//        }
//
//        // Recursively map fields from superclasses
//        mapFieldsRecursive(source, target, sourceClass.getSuperclass(), targetClass.getSuperclass());
//    }
//
//    private static Field getFieldByName(Class<?> clazz, String fieldName) {
//        if (clazz == null) {
//            return null;
//        }
//        try {
//            return clazz.getDeclaredField(fieldName);
//        } catch (NoSuchFieldException e) {
//            // Recursively search in the superclass
//            return getFieldByName(clazz.getSuperclass(), fieldName);
//        }
//    }
//}
package cn.sw.common.utils;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

/**
 * @Description: Mapper映射
 * @Author: 张众森
 * @Date: 2025/5/10
 */
public class Mapper {
    // 定义一个静态的Logger对象，用于记录日志
    private static final Logger logger = Logger.getLogger(Mapper.class.getName());

    // 定义一个泛型方法，用于将源对象映射为目标对象
    public static <S, T> T map(S source, Class<T> targetClass) throws Exception {
        // 记录日志，记录源对象和目标对象的类名
        logger.info("Mapping from " + source.getClass().getName() + " to " + targetClass.getName());
        // 使用目标对象的类名创建一个目标对象
        T target = targetClass.getDeclaredConstructor().newInstance();
        // 调用mapFields方法，将源对象映射到目标对象
        mapFields(source, target);
        // 返回目标对象
        return target;
    }

    // 定义一个私有方法，用于将源对象的字段映射到目标对象的字段
    private static void mapFields(Object source, Object target) throws IllegalAccessException {
        // 如果源对象或目标对象为空，则记录日志并返回
        if (source == null || target == null) {
            logger.warning("Source or target is null");
            return;
        }

        // 获取源对象和目标对象的类名
        Class<?> sourceClass = source.getClass();
        Class<?> targetClass = target.getClass();

        // 记录日志，记录源对象和目标对象的类名
        logger.info("Source class: " + sourceClass.getName());
        logger.info("Target class: " + targetClass.getName());

        // Map fields from source to target, including fields in superclasses
        mapFieldsRecursive(source, target, sourceClass, targetClass);
    }

    //递归
    private static void mapFieldsRecursive(Object source, Object target, Class<?> sourceClass, Class<?> targetClass) throws IllegalAccessException {
        // 如果源类或目标类为空，或者源类为Object类，则递归结束
        if (sourceClass == null || targetClass == null || sourceClass.equals(Object.class)) {
            logger.info("End of recursion");
            return;
        }

        logger.info("Mapping fields from " + sourceClass.getName() + " to " + targetClass.getName());

        for (Field sourceField : sourceClass.getDeclaredFields()) {
            sourceField.setAccessible(true);

            // 跳过 static final 字段
            int modifiers = sourceField.getModifiers();
            if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
                logger.info("Skipping static final field: " + sourceField.getName());
                continue;
            }

            Field targetField = getFieldByName(targetClass, sourceField.getName());
            if (targetField != null) {
                targetField.setAccessible(true);

                // 获取字段值
                Object value = sourceField.get(source);

                // 新增逻辑：将空字符串转为 null
                if (value instanceof String && ((String) value).isEmpty()) {
                    value = null;
                    logger.info("Converted empty string to null for field: " + sourceField.getName());
                }

                // 原有类型检查逻辑保持不变
                if (sourceField.getType().equals(targetField.getType())) {
                    targetField.set(target, value);
                    logger.info("Mapped field: " + sourceField.getName() + " from " + sourceClass.getName() + " to " + targetClass.getName());
                } else {
                    logger.warning("Field type mismatch: " + sourceField.getName() + " in " + sourceClass.getName() + " and " + targetClass.getName());
                }
            } else {
                logger.warning("Field not found in target: " + sourceField.getName() + " in " + targetClass.getName());
            }
        }


        // Recursively map fields from superclasses
        mapFieldsRecursive(source, target, sourceClass.getSuperclass(), targetClass.getSuperclass());
    }

    private static Field getFieldByName(Class<?> clazz, String fieldName) {
        // 如果类为空，则结束搜索
        if (clazz == null) {
            logger.info("Class is null, end of search");
            return null;
        }
        try {
            // 在类中搜索字段
            logger.info("Searching for field: " + fieldName + " in " + clazz.getName());
            return clazz.getDeclaredField(fieldName);
        } catch (NoSuchFieldException e) {
            // 如果字段未找到，则在父类中搜索
            logger.info("Field not found in " + clazz.getName() + ", searching in superclass");
            // Recursively search in the superclass
            return getFieldByName(clazz.getSuperclass(), fieldName);
        }
    }

    /**
     * 将 List<T> 构建的树结构映射为 List<D>
     */
    public static <T, D> List<D> mapTree(List<T> tree, Class<D> targetClass) throws Exception {
        if (tree == null || tree.isEmpty()) {
            return new ArrayList<>();
        }

        List<D> result = new ArrayList<>();

        for (T node : tree) {
            D dto = map(node, targetClass);
            Field childrenFieldInSource = getFieldByName(node.getClass(), "children");
            Field childrenFieldInTarget = getFieldByName(targetClass, "children");

            if (childrenFieldInSource != null && childrenFieldInTarget != null) {
                childrenFieldInSource.setAccessible(true);
                childrenFieldInTarget.setAccessible(true);

                @SuppressWarnings("unchecked")
                List<T> children = (List<T>) childrenFieldInSource.get(node);

                if (children != null && !children.isEmpty()) {
                    List<D> mappedChildren = mapTree(children, targetClass);
                    childrenFieldInTarget.set(dto, mappedChildren);
                }
            }

            result.add(dto);
        }

        return result;
    }

    /**
     * 将源对象列表映射为目标对象列表
     */
    public static <S, T> List<T> mapList(List<S> sourceList, Class<T> targetClass) throws Exception {
        List<T> targetList = new ArrayList<>();

        if (sourceList == null || sourceList.isEmpty()) {
            return targetList; // 空列表或 null 返回空列表
        }

        for (S source : sourceList) {
            T target = map(source, targetClass); // 使用已有的 map 方法进行单个对象映射
            targetList.add(target);
        }

        return targetList;
    }

}
